﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    public enum NEIGHBOUR
    {
        FOUR,
        EIGHT
    }

    /// <summary>
    /// BW2 = bwperim(BW1) returns a binary image containing
    /// only the perimeter pixels of objects in the input image BW1.
    /// A pixel is part of the perimeter if it is nonzero and it is connected
    /// to at least one zero-valued pixel.
    /// The default connectivity is 4 for two dimensions,
    /// 6 for three dimensions, and conndef(ndims(BW), 'minimal')
    /// for higher dimensions.
    /// </summary>
    public class BlackWhitePerimeter : BaseForeBackgroundColorFilter
    {
        //TODO: check if this can be deleted (inheritance)
        protected Dictionary<NEIGHBOUR, List<Point>> m_aNeighbour = new Dictionary<NEIGHBOUR, List<Point>>() { 
            {NEIGHBOUR.EIGHT, Definitions.EnvironmentPointListClockwise},
            {NEIGHBOUR.FOUR, Definitions.EnvironmentPointList4Clockwise}
        };

        //TODO: check if this can be deleted (inheritance)
        protected NEIGHBOUR m_NEIGHBOUR = NEIGHBOUR.EIGHT;

        /// <summary>
        /// Initializes a new instance of the <see cref="BlackWhitePerimeter"/> class.
        /// </summary>
        public BlackWhitePerimeter()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BlackWhitePerimeter"/> class.
        /// </summary>
        /// <param name="_bwperim">The _bwperim.</param>
        internal BlackWhitePerimeter(BlackWhitePerimeter _bwperim)
        {
        }

        //TODO: check if this can be deleted (inheritance)
        /// <summary>
        /// Gets or sets the neighbour.
        /// </summary>
        /// <value>The neighbour.</value>
        public NEIGHBOUR Neighbour
        {
            get { return m_NEIGHBOUR; }
            set { m_NEIGHBOUR = value; }
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            int y = 0;
            int x = 0;
            int nHeight = _bitmap.Height;
            int nWidth = _bitmap.Width;

            Color[] aColor = new Color[m_aNeighbour[m_NEIGHBOUR].Count];

            Color color = Color.Transparent;
            int nForegroundCount = 0;
            int nBackgroundCount = 0;

            UnsafeBitmap bitmapCloned = (UnsafeBitmap)_bitmap.Clone();
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = _bitmap.GetPixel(x, y);

                    if (color == m_ColorBackground) continue;

                    aColor = Segmentation.GetEnvironmentPixelColorArray(bitmapCloned, x, y, Definitions.EnvironmentPointList4Clockwise, aColor);

                    nForegroundCount = 0;
                    nBackgroundCount = 0;

                    foreach (Color colorEnvironment in aColor)
                    {
                        if (colorEnvironment == m_ColorForeground)
                        {
                            nForegroundCount++;
                        }
                        else if (colorEnvironment == m_ColorBackground)
                        {
                            nBackgroundCount++;
                        }
                    }
                    _bitmap.SetPixel(x, y, nBackgroundCount > 0 ? m_ColorForeground : m_ColorBackground);
                }
            }
            bitmapCloned.Dispose();
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new BlackWhitePerimeter(this);
        }
    }
}
